package ch.fhnw.ams.sudoku.gui;

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.util.Map;

import javax.swing.JComponent;

import ch.fhnw.ams.sudoku.SudokuField;

/**
 * Represents the graphic component of a {@link SudokuField}.
 * 
 * @author amsler
 *
 */
public class FieldComponent extends JComponent {

	private static final long serialVersionUID = 1L;
	public static final int DEFAULT_WIDTH = 40;
	public static final int DEFAULT_HEIGHT = 40;
	public static final float DEFAULT_FONT_SIZE = 20.0f;
	public static final int DEFAULT_FRAME_LINE_SIZE = 1;
	public static final Color DEFAULT_FRAME_COLOR = Color.BLACK;
	public static final Color DEFAULT_PUZZLE_NUM_COLOR = Color.BLACK;
	public static final Color DEFAULT_SOLUTION_NUM_COLOR = new Color(48, 63, 150);
	public static final Color DEFAULT_SELECTION_COLOR = new Color(136, 187, 255);
	public static final Color DEFAULT_ERROR_COLOR = new Color(255, 61, 74);
	
	private final int row;
	private final int column;
	
	private SudokuField sudokuField;
	private Color puzzleNumColor;
	private Color solutionNumColor;
	private Color errorColor;
	private boolean isSelected;
	
	@SuppressWarnings("rawtypes")
	private Map desktopHints;
	
	
	/**
	 * Creates a new blank field.
	 * 
	 * @param row
	 *            the row number of {@link GridPanel}
	 * @param column
	 *            the column number of {@link GridPanel}
	 */
	@SuppressWarnings("rawtypes")
	public FieldComponent(int row, int column) {
		this.row = row;
		this.column = column;
		sudokuField = new SudokuField(row, column);
		puzzleNumColor = DEFAULT_PUZZLE_NUM_COLOR;
		solutionNumColor = DEFAULT_SOLUTION_NUM_COLOR;
		errorColor = DEFAULT_ERROR_COLOR;
		setSelected(false);
		
		desktopHints = (Map) Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints");
		setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
		setOpaque(false);
	}
	
	
	@Override
	public void paintComponent(Graphics g) {
		Graphics2D g2d = (Graphics2D) g.create();
		
		//draw frame
		g2d.setColor(DEFAULT_FRAME_COLOR);
		g2d.setStroke(new BasicStroke(DEFAULT_FRAME_LINE_SIZE));
		final int frameY = 0;
		final int frameX = 0;
		final int frameWidth = getWidth() - DEFAULT_FRAME_LINE_SIZE;
		final int frameHeight = getHeight() - DEFAULT_FRAME_LINE_SIZE;
		g2d.drawRect(frameX, frameY, frameWidth, frameHeight);
        
        //draw number
		if (!sudokuField.isEmpty()) {
			int number = sudokuField.getNumber();
			String numStr = Integer.toString(number);
			
			if (sudokuField.isPuzzelNumber()) {
				g2d.setColor(puzzleNumColor);
			} else {
				if (sudokuField.isIncorrect()) {
					g2d.setColor(errorColor);
				} else {
					g2d.setColor(solutionNumColor);
				}
			}
			
			if (desktopHints != null) {
				g2d.addRenderingHints(desktopHints);
			}
			
			Font font = g2d.getFont().deriveFont(Font.BOLD, DEFAULT_FONT_SIZE);
			g2d.setFont(font);
			int strPosX = 13;
			int strPoxY = 28;
			g2d.drawString(numStr, strPosX, strPoxY);
		}
		
		//draw selected state
		if (isSelected) {
			g2d.setColor(DEFAULT_SELECTION_COLOR);
			final int selectedRectX = DEFAULT_FRAME_LINE_SIZE;
			final int selectedRectY = DEFAULT_FRAME_LINE_SIZE;
			final int selectedRectWidth = getHeight() - DEFAULT_FRAME_LINE_SIZE * 2;
			final int selectedRectHeight = getWidth() - DEFAULT_FRAME_LINE_SIZE * 2;
			AlphaComposite alphaComposit = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .45f);
			g2d.setComposite(alphaComposit);
			g2d.fillRect(selectedRectX, selectedRectY, selectedRectWidth, selectedRectHeight);
		}
		
		g2d.dispose();
	}

	/**
	 * Gets the sudoku field.
	 *
	 * @return the sudoku field
	 */
	public SudokuField getSudokuField() {
		return sudokuField;
	}
	
	
	/**
	 * Sets the sudoku field.
	 *
	 * @param sudokuField the new sudoku field
	 */
	public void setSudokuField(SudokuField sudokuField) {
		this.sudokuField = sudokuField;
	}

	/**
	 * Checks if this component is selected
	 *
	 * @return true, if is selected
	 */
	public boolean isSelected() {
		return isSelected;
	}

	/**
	 * Sets the selected field.
	 * 
	 * @param isSelected
	 *            <code>true</code> if this field is selected
	 */
	public void setSelected(boolean isSelected) {
		this.isSelected = isSelected;
	}
	
	/**
	 * Returns the row number of {@link GridPanel}
	 */
	public int getRow() {
		return row;
	}
	
	/**
	 * Returns the column number of {@link GridPanel}
	 */
	public int getColumn() {
		return column;
	}

}
